#pragma once

#include "io.h"

#define U3D_FIFO_OFFSET                 (SSUSB_DEV_BASE + 0x0300)
#define U3D_FIFO(x)                     (U3D_FIFO_OFFSET + ((x) * 0x10))
#define USB_FIFO(x)                     (U3D_FIFO(x))

#define IO_PHYS 0x10000000
#define U3D_BASE                       (IO_PHYS + 0x01270000)
#define SSUSB_DEV_BASE                                 (U3D_BASE + 0x1000)
#define SSUSB_EPCTL_CSR_BASE                   (U3D_BASE + 0x1800)
#define U3D_EP_RST                       (SSUSB_EPCTL_CSR_BASE+0x0004)
#define EP0_RST                          (0x1 << 0)

#define U3D_EP0CSR                       (SSUSB_DEV_BASE+0x0100)
#define U3D_TX1CSR0                      (SSUSB_DEV_BASE+0x0110)

#define EP0_RXPKTRDY                     (0x1 << 16) 
#define EP0_SETUPPKTRDY (0x1 << 17)
#define EP0_TXPKTRDY                     (0x1 << 18)
#define EP0_DATAEND                      (0x1 << 19)
#define EP0_SENTSTALL (0x1 << 22)
#define EP0_W1C_BITS                     (~(EP0_RXPKTRDY | EP0_SETUPPKTRDY | EP0_SENTSTALL))

#define TX_TXPKTRDY                  (0x1 << 16) 


#define USB_SETMASK(addr, mask) \
        do { \
                WRITE32(addr, READ32(addr) | mask); \
        } while (0)
#define USB_CLRMASK(addr, mask)\
        do { \
        WRITE32(addr, READ32(addr) &~mask);\
        } while (0)

#define USB_EP0CSR_SETMASK(mask) \
        do { \
        UINT32 _temp = READ32(U3D_EP0CSR); \
        WRITE32(U3D_EP0CSR, (_temp & EP0_W1C_BITS) | (mask)); \
        } while (0);


#define USB_END_OFFSET(_bEnd, _bOffset) ((0x10*(_bEnd-1)) + _bOffset)
#define USB_WRITECSR32( _bOffset, _bEnd, _bData) \
        WRITE32(USB_END_OFFSET(_bEnd, _bOffset), _bData)
#define USB_READCSR32(_bOffset, _bEnd) \
        READ32(USB_END_OFFSET(_bEnd, _bOffset))

#define USB_DIR_OUT 0
#define USB_DIR_IN            0x80


#define USB_SR_OUT_EP 4